/*******************************************************************************
*
*   FILE NAME:
*       GameWindow.cpp - GameWindow class implementation
*
*   DESCRIPTION:
*       The system window associated with a Game.
*
*******************************************************************************/
#include "GameWindow.h"

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

#define GAME_WINDOW_CLASS_NAME L"GameWindow"

static WNDCLASSEX s_game_window_class;
static uint32 s_game_window_count = 0;

uint64 create_window( const String& title, uint32 width, uint32 height, uint32 pos_x, uint32 pos_y );
LRESULT CALLBACK WndProc( HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam );

GameWindow::GameWindow( const String& title, uint32 width, uint32 height )
    : mHeight( height ),
      mWidth( width ),
      mTitle( title ),
      mVisible( FALSE )
{
    mHandle = create_window( mTitle, mWidth, mHeight, CW_USEDEFAULT, CW_USEDEFAULT );
    RECT rect;
    GetWindowRect( ( HWND ) mHandle, &rect );
    mPosX = rect.left;
    mPosY = rect.top;
}

GameWindow::GameWindow( const String& title, uint32 width, uint32 height, uint32 pos_x, uint32 pos_y )
    : mHeight( height ),
      mWidth( width ),
      mPosX( pos_x ),
      mPosY( pos_y ),
      mTitle( title ),
      mVisible( FALSE )
{
    mHandle = create_window( mTitle, mWidth, mHeight, mPosX, mPosY );
}

GameWindow::~GameWindow( void )
{
    if( --s_game_window_count == 0 )
    {
        UnregisterClass( s_game_window_class.lpszClassName, GetModuleHandle( NULL ) );
    }
}

boolean GameWindow::Update( void )
{
    MSG msg;
    if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );

        if( msg.message == WM_QUIT )
        {
            return FALSE;
        }
    }

    return TRUE;
}

uint64 GameWindow::GetHandle( void )
{
    return mHandle;
}

uint32 GameWindow::GetHeight( void )
{
    return mHeight;
}

uint32 GameWindow::GetPositionX( void )
{
    return mPosX;
}

uint32 GameWindow::GetPositionY( void )
{
    return mPosY;
}

String GameWindow::GetTitle( void )
{
    return mTitle;
}

uint32 GameWindow::GetWidth( void )
{
    return mWidth;
}

boolean GameWindow::IsFullscreen( void )
{
    return mFullscreen;
}

boolean GameWindow::IsVisible( void )
{
    return mVisible;
}

void GameWindow::SetFullscreen( boolean fullscreen )
{
    mFullscreen = fullscreen;
}

void GameWindow::SetHeight( uint32 height )
{
    mHeight = height;
}

void GameWindow::SetPositionX( uint32 pos_x )
{
    mPosX = pos_x;
}

void GameWindow::SetPositionY( uint32 pos_y )
{
    mPosY = pos_y;
}

void GameWindow::SetTitle( const String& title )
{
    mTitle = title;
    SetWindowText( ( HWND ) mHandle, title );
}

void GameWindow::SetVisible( boolean visible )
{
    if( visible && !mVisible )
    {
        ShowWindow( ( HWND ) mHandle, SW_SHOW );
    }
    else if( !visible && mVisible )
    {
        ShowWindow( ( HWND ) mHandle, SW_HIDE );
    }
    mVisible = visible;
}

void GameWindow::SetWidth( uint32 width )
{
    mWidth = width;
}

uint64 create_window( const String& title, uint32 width, uint32 height, uint32 pos_x, uint32 pos_y )
{
    if( s_game_window_count++ == 0 )
    {
        memset( &s_game_window_class, 0, sizeof( s_game_window_class ) );
        s_game_window_class.cbSize = sizeof( s_game_window_class );
        s_game_window_class.style = CS_HREDRAW | CS_VREDRAW;
        s_game_window_class.lpfnWndProc = WndProc;
        s_game_window_class.hInstance = GetModuleHandle( NULL );
        s_game_window_class.hCursor = LoadCursor( NULL, IDC_ARROW );
        s_game_window_class.hbrBackground = ( HBRUSH ) COLOR_WINDOW;
        s_game_window_class.lpszClassName = GAME_WINDOW_CLASS_NAME;

        RegisterClassEx( &s_game_window_class );
    }

    RECT window_rectangle = { 0, 0, width, height };
    AdjustWindowRect( & window_rectangle, WS_OVERLAPPEDWINDOW, FALSE );

    return ( uint64 ) CreateWindowEx( NULL,
                                      s_game_window_class.lpszClassName,
                                      title,
                                      WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME ^ WS_MAXIMIZEBOX,
                                      pos_x,
                                      pos_y,
                                      window_rectangle.right - window_rectangle.left,
                                      window_rectangle.bottom - window_rectangle.top,
                                      NULL,
                                      NULL,
                                      GetModuleHandle( NULL ),
                                      NULL );
}

LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
        {
            PostQuitMessage( 0 );
            return 0;
        } break;
    }
    return DefWindowProc( hWnd, msg, wParam, lParam );
}
